#ifndef SERVER_H
#define SERVER_H
#include "User.h"

typedef unsigned long long ULL;

std::pair<ULL, ULL> hash(const std::string &fish);

inline double grade(std::string target, std::string substr) {
  if (target.empty()) {
    return 1;
  }
  if (substr.length() > target.length()) {
    return 0;
  }
  int i = 0;
  for (i = 0; i < target.length() && i < substr.length(); i += 2) {
    if (target.substr(i, 2) != substr.substr(i, 2)) {
      return (double)i / target.length();
    }
  }
  return (double)i / target.length();
}

class Interface;
class Server {
public:
  friend class Interface;
  Server() {
    init_user_pool();
    init_sold_list();
    init_inventory();
    admin = nullptr;
    current_user = nullptr;
  }
  // TO INIT FROM FILE
  void init_user_pool();
  void init_sold_list();
  void init_inventory();
  // FOR LOGIN AND LOGOUT
  bool admin_login(const std::string &name, const std::string &psw);
  bool user_login(const std::string &name, const std::string &psw);
  bool user_sign_up(const std::string &name, const std::string &psw);
  void admin_logout();
  void user_logout();
  // FOR ADMIN OPERATION

  // to view inventory or sold_list;
  const cart admin_view(bool is_inventory);
  void admin_add_good(const good &g);
  int admin_del_good(int index);
  void admin_change_price(int new_price, int index);
  void admin_change_quantity(int new_quan, int index);

  // FOR USER OPERATION

  // for every user acts the same : return a cart selected from the inventory,
  // note that zero good do not be loaded.
  const cart view_invent();
  // to find every good i which satisfies selector(target, i);
  const cart user_find(
      std::string target, std::string option,
      bool (*selector)(std::string, std::string, const good &) =
          [](std::string a, std::string option, const good &b) -> bool {
        return a == b.name;
      });
  // to return u->cart;
  const cart user_view_cart();
  int user_add_cart(good g);
  // to delete every good in u's cart which satisfies selector(good, name,
  // brand, selec);
  int user_del_cart(
      std::string name, std::string brand, int num,
      bool (*selector)(good &, std::string name, std::string brand) =
          [](good &a, std::string name, std::string brand) -> bool {
        return (a.name == name || name.empty()) &&
               (a.brand == brand || brand.empty());
      });
  bool user_purchase();
  void feed_me(double count);
  void write_user();
  void write_sold_list();
  void write_inventory();
  void write_cart(User *sb); // sb, short for super boy. XD

private:
  // User* pool
  std::vector<User *> user_pool;
  std::vector<std::pair<unsigned long long, unsigned long long>> key_pool;
  cart sold_list;
  inventory invent;
  Admin *admin;
  User *current_user;
};
#endif